package org.wu.framework.lazy.orm.database.lambda.stream.function;

import org.wu.framework.core.CamelAndUnderLineConverter;
import org.wu.framework.lazy.orm.database.lambda.stream.support.LambdaMeta;
import org.wu.framework.lazy.orm.database.lambda.stream.support.SerializedLambdaMeta;
import org.wu.framework.lazy.orm.database.lambda.stream.support.toolkit.ReflectionKit;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * @author Jia wei Wu
 */
public class SnippetUtil {

    /**
     * 解析 Snippet
     * @param func Snippet
     * @return LambdaMeta
     * @param <T> 范型
     */
    public static <T> LambdaMeta extract(Snippet<T, ?> func) {
        try {
            Method method = func.getClass().getDeclaredMethod("writeReplace");
            final Method accessible = ReflectionKit.setAccessible(method);
            final Object invoke = accessible.invoke(func);
            return new SerializedLambdaMeta((SerializedLambda) invoke);
        } catch (NoSuchMethodException e) {
            if (func instanceof Proxy) {
//                return new ProxyLambdaMeta((Proxy) func);
                return null;
            }
            String message = "Cannot find method writeReplace, please make sure that the lambda composite class is currently passed in";
            throw new RuntimeException(message);
        } catch (InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析 Snippet 为字段名称
     * @param func Snippet
     * @return 字段名称
     * @param <T> 范型
     */
    public static <T> String extractFieldName(Snippet<T, ?> func) {
        final LambdaMeta meta = SnippetUtil.extract(func);
        assert meta != null;
        final String methodName = meta.methodName();
        return CamelAndUnderLineConverter.methodToField(methodName);
    }


    /**
     * 解析 Snippet 为字段下划线
     * @param func Snippet
     * @return 字段名称
     * @param <T> 范型
     */
    public static <T> String extractFieldNameHumpToLine2(Snippet<T, ?> func) {
        final String field = extractFieldName(func);
        return CamelAndUnderLineConverter.humpToLine2(field);
    }

}
